package com.yonyou.pmclouds.plantemplate.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoInsertMultiProcessor;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoUpdateProcessor;
import com.yonyou.pmclouds.basecom.bp.template.MultiInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.plantemplate.entity.ScheduleTemplateItemVO;
import com.yonyou.pmclouds.plantemplate.entity.ScheduleTemplateVO;
import com.yonyou.pmclouds.plantemplate.mapper.ScheduleTemplateItemMapper;
import com.yonyou.pmclouds.plantemplate.processor.ScheduleTemplateItemInsertDefaultValueProcessor;
import com.yonyou.pmclouds.plantemplate.processor.ScheduleTemplateItemRequiredCheckProcessor;
import com.yonyou.pmclouds.plantemplate.rmiitf.IScheduleTemplateHandleService;
import com.yonyou.pmclouds.plantemplate.rmiitf.IScheduleTemplateItemQueryService;
import com.yonyou.pmclouds.plantemplate.rmiitf.IScheduleTemplateItemService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * @Description: 计划模板任务项服务类
 * @Author: zhangzhonghao
 * @Date:  2020-03-27
 */
@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = IScheduleTemplateItemService.class)
public class ScheduleTemplateItemServiceImpl implements IScheduleTemplateItemService {

    @Autowired
    private ScheduleTemplateItemMapper templateItemMapper;

    @Autowired
    private IScheduleTemplateHandleService templateHandleService;

    @Autowired
    private ScheduleTemplateItemRequiredCheckProcessor requiredCheckProcessor;

    @Autowired
    private AuditInfoInsertMultiProcessor<ScheduleTemplateItemVO> auditInfoInsertMultiProcessor;

    @Autowired
    private AuditInfoUpdateProcessor<ScheduleTemplateItemVO> auditInfoUpdateProcessor;

    @Autowired
    private IScheduleTemplateItemQueryService templateItemQueryService;

    @Override
    public ScheduleTemplateVO insert(ScheduleTemplateVO templateVO) throws BusinessException {
        ScheduleTemplateItemInsertDefaultValueProcessor defaultValueProcessor = new ScheduleTemplateItemInsertDefaultValueProcessor();

        templateHandleService.addIteratorBeforeProcessor(requiredCheckProcessor);

        templateHandleService.addIteratorBeforeProcessor(defaultValueProcessor);

        templateHandleService.handle(templateVO, templateVO);

        // 获取需要新增的任务项
        List<ScheduleTemplateItemVO> insertItemList = defaultValueProcessor.getInsertScheduleItemList();

        // 设置前置任务关联主键映射
        Map<String, String> codeWithPKMap = defaultValueProcessor.getCodeWithPKMap();
        setDependPlan(insertItemList, codeWithPKMap);

        this.insert(insertItemList.toArray(new ScheduleTemplateItemVO[]{}));

        return templateVO;
    }



    @Override
    public ScheduleTemplateVO update(ScheduleTemplateVO templateVO) throws BusinessException {
        // 获取删除的任务项
        ScheduleTemplateItemVO[] deleteItemVOS = null;
        if (templateVO.getDeletePlan() != null && templateVO.getDeletePlan().length > 0) {
            deleteItemVOS = deleteScheduleItemByPks(templateVO.getDeletePlan());
        }

        ScheduleTemplateItemInsertDefaultValueProcessor defaultValueProcessor = new ScheduleTemplateItemInsertDefaultValueProcessor();

        // 校验必填项
        templateHandleService.addIteratorBeforeProcessor(requiredCheckProcessor);

        // 赋默认值
        templateHandleService.addIteratorBeforeProcessor(defaultValueProcessor);

        // 迭代处理任务业务逻辑
        templateHandleService.handle(templateVO, templateVO);

        // 获取新增任务项
        List<ScheduleTemplateItemVO> insertItemList = defaultValueProcessor.getInsertScheduleItemList();

        // 获取修改任务项
        List<ScheduleTemplateItemVO> updateItemList = defaultValueProcessor.getUpdateScheduleItemList();

        // 设置前置任务主键映射
        Map<String, String> codeWithPKMap = defaultValueProcessor.getCodeWithPKMap();
        setDependPlan(insertItemList, codeWithPKMap);
        setDependPlan(updateItemList, codeWithPKMap);

        this.insert(filterDeleteItem(insertItemList, deleteItemVOS).toArray(new ScheduleTemplateItemVO[]{}));
        this.update(filterDeleteItem(updateItemList, deleteItemVOS).toArray(new ScheduleTemplateItemVO[]{}));

        return templateVO;
    }

    @Override
    public ScheduleTemplateVO delete(ScheduleTemplateVO templateVO) throws BusinessException {
        Map<String, List<ScheduleTemplateItemVO>> itemMap = templateItemQueryService.queryByPkSchedules(new String[]{templateVO.getPkScheduleTemplate()});
        if(itemMap == null){
            return templateVO;
        }

        delete(itemMap.get(templateVO.getPkScheduleTemplate()).toArray(new ScheduleTemplateItemVO[]{}));
        return templateVO;
    }

    @Override
    public ScheduleTemplateItemVO[] insert(ScheduleTemplateItemVO[] templateItemVOS) throws BusinessException {
        if (templateItemVOS == null || templateItemVOS.length <= 0) {
            return templateItemVOS;
        }

        MultiInsertBpTemplate<ScheduleTemplateItemVO> insertBpTemplate = new MultiInsertBpTemplate<>(templateItemMapper, false);
        insertBpTemplate.addBeforeProcessor(auditInfoInsertMultiProcessor);

        return insertBpTemplate.insert(templateItemVOS);
    }

    @Override
    public ScheduleTemplateItemVO[] update(ScheduleTemplateItemVO[] templateItemVOS) throws BusinessException {
        if (templateItemVOS == null || templateItemVOS.length <= 0) {
            return templateItemVOS;
        }

        SingleUpdateBpTemplate<ScheduleTemplateItemVO> updateBpTemplate = new SingleUpdateBpTemplate<>(templateItemMapper,
                ScheduleTemplateItemVO.UPDATE_FIELDS);
        updateBpTemplate.addBeforeProcessor(auditInfoUpdateProcessor);
        for (ScheduleTemplateItemVO itemVO : templateItemVOS) {
            updateBpTemplate.update(itemVO);
        }

        return templateItemVOS;
    }

    @Override
    public ScheduleTemplateItemVO[] delete(ScheduleTemplateItemVO[] templateItemVOS) throws BusinessException {
        if (templateItemVOS == null || templateItemVOS.length <= 0) {
            return templateItemVOS;
        }

        SingleDeleteBpTemplate<ScheduleTemplateItemVO> deleteBpTemplate = new SingleDeleteBpTemplate<>(templateItemMapper);
        deleteBpTemplate.addBeforeProcessor(auditInfoUpdateProcessor);

        for (ScheduleTemplateItemVO itemVO : templateItemVOS) {
            deleteBpTemplate.delete(itemVO);
        }

        return templateItemVOS;
    }

    private ScheduleTemplateItemVO[] deleteScheduleItemByPks(String[] pkItems) throws BusinessException {
        List<ScheduleTemplateItemVO> itemVOS = templateItemQueryService.queryByPkItems(pkItems);
        if (itemVOS == null || itemVOS.size() <= 0) {
            return null;
        }

        List<ScheduleTemplateItemVO> deleteItemVOS = new ArrayList<>();
        // 去除判断，因为可能父级与子级主键均存在了删除字段上
        Set<String> hasDeletePkItemSet = new HashSet<>();
        for (ScheduleTemplateItemVO itemVO : itemVOS) {
            getDeleteItemVO(deleteItemVOS, hasDeletePkItemSet, itemVO);
        }

        return this.delete(deleteItemVOS.toArray(new ScheduleTemplateItemVO[]{}));

    }

    private void getDeleteItemVO(List<ScheduleTemplateItemVO> deleteItemVOS, Set<String> hasDeletePkItemSet, ScheduleTemplateItemVO itemVO){
        if(!hasDeletePkItemSet.contains(itemVO.getPkScheduleTemplateItem())){
            deleteItemVOS.add(itemVO);
            hasDeletePkItemSet.add(itemVO.getPkScheduleTemplateItem());
        }

        if (itemVO.getChildren() != null && itemVO.getChildren().length > 0) {
            for (ScheduleTemplateItemVO childItemVO : itemVO.getChildren()) {
                getDeleteItemVO(deleteItemVOS, hasDeletePkItemSet, childItemVO);
            }
        }
    }

    /**
     * 删除父级，同时也删除子级，过滤掉已经被删除的数据
     * @param itemVOList 任务项
     * @param deleteItemVOS 已删除任务项
     */
    private List<ScheduleTemplateItemVO> filterDeleteItem(List<ScheduleTemplateItemVO> itemVOList, ScheduleTemplateItemVO[] deleteItemVOS){
        if(deleteItemVOS == null || deleteItemVOS.length <= 0){
            return itemVOList;
        }
        List<ScheduleTemplateItemVO> newItemVOList = new ArrayList<>();
        Map<String, ScheduleTemplateItemVO> deleteItemMap = new HashMap<>();
        for(ScheduleTemplateItemVO itemVO : deleteItemVOS){
            deleteItemMap.put(itemVO.getPkScheduleTemplateItem(), itemVO);
        }

        for(ScheduleTemplateItemVO itemVO : itemVOList){
            if(deleteItemMap.get(itemVO.getPkScheduleTemplateItem()) == null){
                newItemVOList.add(itemVO);
            }
        }

        return newItemVOList;

    }

    private void setDependPlan(List<ScheduleTemplateItemVO> itemVOList, Map<String, String> codeWithPKMap) throws BusinessException {
        if (itemVOList != null) {
            for (ScheduleTemplateItemVO itemVO : itemVOList) {
                if(StringUtils.isNotEmpty(itemVO.getDependPlanName())) {
                    itemVO.setDependPlan(codeWithPKMap.get(itemVO.getDependPlanName()));
                }
            }
        }
    }
}
